/**
 * <p>Title: liteflow</p>
 * <p>Description: 轻量级的组件式流程框架</p>
 * @author Bryan.Zhang
 * @email weenyc31@163.com
 * @Date 2020/4/1
 */
package io.mft.flow.core.executable;

import java.util.List;

import org.apache.commons.collections4.CollectionUtils;

import io.mft.commons.exception.MFTException;
import io.mft.commons.function.ExecuteReturn;
import io.mft.flow.core.executable.condition.AsyncCondition;
import io.mft.flow.data.ChainContext;

public class Chain implements Executable {

	private String chainId;

	private List<Condition> conditionList;

	private ChainCondition rootChainCondition;

	public Chain(String chainId, List<Condition> conditionList) {
		this.chainId = chainId;
		this.conditionList = conditionList;
		if (conditionList.size() > 0) {
			rootChainCondition = new ChainCondition(conditionList.get(0));
			buildChainCondition(0, rootChainCondition, conditionList);
		}

	}
	
	public boolean existAsyncCondition() {
		boolean s=false;
		for (Condition condition : conditionList) {
			if (condition instanceof AsyncCondition) {
				s=true;
				break;
			}
		}
		return s;
	}
	private void buildChainCondition(int index, ChainCondition chainCondition, List<Condition> conditionList) {
		if (index > conditionList.size() - 1) {
			return;
		}
		chainCondition.setCondition(conditionList.get(index));
		chainCondition.setChain(this);
		chainCondition.setChainConditionDriver(conditionList.get(index).chainConditionDriver());
		if (index+1<=(conditionList.size() - 1)) {
			ChainCondition indexChainCondition = new ChainCondition(conditionList.get(index+1));
			indexChainCondition.setChain(chainCondition.getChain());
			chainCondition.setNextChainCondition(indexChainCondition);
			String joinUniqueId = chainCondition.getCondition().last().getUniqueId() + "&"+ indexChainCondition.getCondition().first().getUniqueId();
			indexChainCondition.setPreviousJoinUniqueId(joinUniqueId);
			chainCondition.setNextJoinUniqueId(joinUniqueId);
			chainCondition.getCondition().chainConditionDriver().chainCondition(chainCondition);
			chainCondition.setChainConditionDriver(chainCondition.getCondition().chainConditionDriver());
			int nextIndex = index + 1;
			buildChainCondition(nextIndex, indexChainCondition, conditionList);
		}

	}

	public List<Condition> getConditionList() {
		return conditionList;
	}

	public String getChainId() {
		return chainId;
	}

	public void setChainId(String chainId) {
		this.chainId = chainId;
	}

	@Override
	public ExecuteReturn execute(ChainContext context) throws Exception {
		if (CollectionUtils.isEmpty(conditionList)) {
			throw new MFTException("no conditionList in this chain[" + chainId + "]");
		}
		ExecuteReturn executeReturn=rootChainCondition.execute(context);
		return executeReturn;
	}

	
	@Override
	public ExecutableType getType() {
		return ExecutableType.CHAIN;
	}

	@Override
	public String getId() {
		return chainId;
	}
}
